﻿using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Casamiel.API.Application.Models;
using Casamiel.API.Application.Services;
using Casamiel.API.Infrastructure.Middlewares;
using Casamiel.Application;
using Casamiel.Common;
using Casamiel.Domain;
using Casamiel.Domain.Entity;
using MediatR;
using Microsoft.Extensions.Options;

namespace Casamiel.API.Application.Commands
{
    /// <summary>
    /// Login command handler.
    /// </summary>
    public sealed class LoginCommandHandler : BaseCommandHandler, IRequestHandler<LoginCommand, Tuple<Member, TokenEntity, string>>
    {
        private readonly CasamielSettings _casamielSettings;
        private readonly IStoreApiService _storeApiService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iicApiService"></param>
        /// <param name="memberCard"></param>
        /// <param name="mobileCheckCode"></param>
        /// <param name="userLogService"></param>
        /// <param name="memberService"></param>
        /// <param name="tokenProvider"></param>
        /// <param name="optionsSnapshot"></param>
        /// <param name="storeApiService"></param>
        public LoginCommandHandler(IIcApiService iicApiService,
            IMemberCardService memberCard,
              IMobileCheckCode mobileCheckCode, IUserLogService userLogService, IMemberService memberService, ITokenProvider tokenProvider, IOptionsSnapshot<CasamielSettings> optionsSnapshot
            , IStoreApiService storeApiService) : base(iicApiService, memberCard, mobileCheckCode, memberService, userLogService, tokenProvider)
        {
            if (optionsSnapshot is null) {
                throw new ArgumentNullException(nameof(optionsSnapshot));
            }

            _casamielSettings = optionsSnapshot.Value;
            _storeApiService = storeApiService;
        }
        /// <summary>
        /// Handle the specified request and cancellationToken.
        /// </summary>
        /// <returns>The handle.</returns>
        /// <param name="request">Request.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        public async Task<Tuple<Member, TokenEntity, string>> Handle(LoginCommand request, CancellationToken cancellationToken)
        {
            if (request == null) {
                throw new ArgumentNullException(nameof(request));
            }

            var member = await MemberService.FindAsync<ICasaMielSession>(request.Mobile).ConfigureAwait(false);
            if (member == null) {
                member = new Member { Mobile = request.Mobile, CreateDate = DateTime.Now, LastLoginDate = DateTime.Now, Source = request.Source };
                await MemberService.AddAsync<ICasaMielSession>(member).ConfigureAwait(false);

            } else {
                member.LastLoginDate = DateTime.Now;
                //await MemberService.UpdateAsync<ICasaMielSession>(member).ConfigureAwait(false);
                await MemberService.UpdateLastLoginDateAsync<ICasaMielSession>(member.ID, DateTime.Now).ConfigureAwait(false);
            }

            var tokens = TokenProvider.GenerateToken(request.Mobile);

            var m = await MemberService.FindAsync<ICasaMielSession>(request.Mobile, request.LoginType, false).ConfigureAwait(false);
            if (m != null) {
                m.Access_Token = tokens.access_token;
                m.UpdateTime = DateTime.Now;
                m.Login_Count++;
                m.Expires_In = tokens.expires_in;
                m.Resgistration_Id = request.Registration_Id;
                await MemberService.UpdateAsync<ICasaMielSession>(m).ConfigureAwait(false);
            } else {
                m = new MemberAccessToken {
                    Access_Token = tokens.access_token,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    Login_Count = 1,
                    Login_Type = request.LoginType,
                    Mobile = request.Mobile,
                    Expires_In = tokens.expires_in,
                    Resgistration_Id = request.Registration_Id
                };
                await MemberService.AddAsync<ICasaMielSession>(m).ConfigureAwait(false);

                if (_casamielSettings.ApiName == "doncoApi" && !string.IsNullOrEmpty(request.InvitationCode)) {
                    try {
                        await _storeApiService.AddReferral(request.Mobile, request.InvitationCode).ConfigureAwait(false);
                    } catch (Exception ex) {
                        this.Logger.Error($"AddReferral:{ex.StackTrace}");
                    }

                }

            }
            string cardno = "";
            var list = await MemberCardService.GetListAsync<ICasaMielSession>(request.Mobile).ConfigureAwait(false);
            if (list.Count > 0) {
                var cardinfo = list.Where(c => c.IsBind == true).FirstOrDefault();
                if (cardinfo != null) {
                    cardno = cardinfo.CardNO;
                }
            }
            var logdata = new UserLog { Url = request.RequestUrl, OPInfo = $"用户登陆", OPTime = DateTime.Now, UserName = request.Mobile, UserIP = request.UserIP };
            await UserLogService.AddAsync<ICasaMielSession>(logdata).ConfigureAwait(false);
            //  string key = Constant.TOKEN_PREFIX + data.mobile + "_" + loginType;
            Tuple<Member, TokenEntity, string> tuple = new Tuple<Member, TokenEntity, string>(member, tokens, cardno);
            return tuple;
        }
    }
}
